package cn.chengpengper.seckill.goods.service.impl;

import cn.chengpengper.seckill.common.code.HttpCode;
import cn.chengpengper.seckill.common.constants.SeckillConstants;
import cn.chengpengper.seckill.common.exception.SeckillException;
import cn.chengpengper.seckill.common.model.enums.SeckillGoodsStatus;
import cn.chengpengper.seckill.goods.domain.event.SeckillGoodsEvent;
import cn.chengpengper.seckill.goods.model.entity.SeckillGoods;
import cn.chengpengper.seckill.goods.repository.SeckillGoodsRepository;
import cn.chengpengper.seckill.goods.service.SeckillGoodsDomainService;
import cn.chengpengper.seckill.mq.MessageSenderService;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * @author chengpeng.hu
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SeckillGoodsDomainServiceImpl implements SeckillGoodsDomainService {

    private final SeckillGoodsRepository seckillGoodsRepository;

    private final MessageSenderService messageSenderService;

    @Value("${message.mq.type}")
    private String eventType;

    @Override
    public void saveSeckillGoods(SeckillGoods seckillGoods) {
        log.info("SeckillGoodsDomainService|发布秒杀商品|{}", JSON.toJSON(seckillGoods));
        if (seckillGoods == null || !seckillGoods.validateParams()) {
            throw new SeckillException(HttpCode.PARAMS_INVALID);
        }
        seckillGoods.setStatus(SeckillGoodsStatus.PUBLISHED.getCode());
        seckillGoodsRepository.saveSeckillGoods(seckillGoods);
        log.info("SeckillGoodsDomainService|秒杀商品已经发布|{}", seckillGoods.getId());

        SeckillGoodsEvent seckillGoodsEvent = new SeckillGoodsEvent(seckillGoods.getId(), seckillGoods.getActivityId(), SeckillGoodsStatus.PUBLISHED.getCode(), getTopicEvent());
        messageSenderService.send(seckillGoodsEvent);
        log.info("SeckillGoodsDomainService|秒杀商品事件已经发布|{}", seckillGoods.getId());
    }

    @Override
    public SeckillGoods getSeckillGoodsId(Long id) {
        return seckillGoodsRepository.getSeckillGoodsId(id);
    }

    @Override
    public List<SeckillGoods> getSeckillGoodsByActivityId(Long activityId) {
        return seckillGoodsRepository.getSeckillGoodsByActivityId(activityId);
    }

    @Override
    public void updateStatus(Integer status, Long id) {
        log.info("SeckillGoodsDomainService|更新秒杀商品状态|{}", id);
        if (Objects.isNull(id)) {
            throw new SeckillException(HttpCode.PARAMS_INVALID);
        }
        SeckillGoods seckillGoods = seckillGoodsRepository.getSeckillGoodsId(id);
        if (Objects.isNull(seckillGoods)) {
            throw new SeckillException(HttpCode.GOODS_NOT_EXISTS);
        }
        //更新状态状态
        seckillGoodsRepository.updateStatus(status, id);
        log.info("SeckillGoodsDomainService|秒杀商品状态已经更新|{},{}", id, status);

        SeckillGoodsEvent seckillGoodsEvent = new SeckillGoodsEvent(seckillGoods.getId(), seckillGoods.getActivityId(), status, getTopicEvent());
        messageSenderService.send(seckillGoodsEvent);
        log.info("SeckillGoodsDomainService|秒杀商品事件已经发布|{}", seckillGoodsEvent.getId());
    }

    @Override
    public boolean decAvailableStock(Integer count, Long id) {
        log.info("SeckillGoodsDomainService|更新秒杀商品库存|{}", id);
        if (Objects.isNull(count) || count <= 0 || Objects.isNull(id)) {
            throw new SeckillException(HttpCode.PARAMS_INVALID);
        }
        SeckillGoods seckillGoods = seckillGoodsRepository.getSeckillGoodsId(id);
        if (Objects.isNull(seckillGoods)) {
            throw new SeckillException(HttpCode.GOODS_NOT_EXISTS);
        }
        boolean isUpdate = seckillGoodsRepository.decAvailableStock(count, id) > 0;
        if (isUpdate) {
            log.info("SeckillGoodsDomainService|秒杀商品库存已经更新|{}", id);
            SeckillGoodsEvent seckillGoodsEvent = new SeckillGoodsEvent(seckillGoods.getId(), seckillGoods.getActivityId(), seckillGoods.getStatus(), getTopicEvent());
            messageSenderService.send(seckillGoodsEvent);
            log.info("SeckillGoodsDomainService|秒杀商品库存事件已经发布|{}", id);
        } else {
            log.info("SeckillGoodsDomainService|秒杀商品库存未更新|{}", id);
        }
        return isUpdate;
    }

    @Override
    public boolean decDbAvailableStock(Integer count, Long id) {
        log.info("扣减秒杀商品库存|{}", id);
        if (Objects.isNull(count) || count <= 0 || Objects.isNull(id)) {
            throw new SeckillException(HttpCode.PARAMS_INVALID);
        }
        return seckillGoodsRepository.decAvailableStock(count, id) > 0;
    }

    @Override
    public boolean incDbAvailableStock(Integer count, Long id) {
        log.info("增加秒杀商品库存|{}", id);
        if (Objects.isNull(count) || count <= 0 || Objects.isNull(id)) {
            throw new SeckillException(HttpCode.PARAMS_INVALID);
        }
        return seckillGoodsRepository.incAvailableStock(count, id) > 0;
    }

    @Override
    public Integer getAvailableStockById(Long id) {
        return seckillGoodsRepository.getAvailableStockById(id);
    }

    /**
     * 获取主题事件
     */
    private String getTopicEvent() {
        return SeckillConstants.EVENT_PUBLISH_TYPE_ROCKETMQ.equals(eventType) ? SeckillConstants.TOPIC_EVENT_ROCKETMQ_GOODS : SeckillConstants.TOPIC_EVENT_COLA;
    }

}

